From: cl349@firebug.cl.cam.ac.uk Date: Fri, 11 Mar 2005 00:19:45 +0000 (+0000) Subject: bitkeeper revision 1.1159.258.42 (4230e421NhFkCppVay5rDH0tzHn2bQ) X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~17827^2~50 X-Git-Url: https://dgit.raspbian.org/%22http://www.example.com/cgi/%22/%22http:/www.example.com/cgi/%22?a=commitdiff_plain;h=ba3ece2d2e1312b9062b32ae249e662795a91f76;p=xen.git bitkeeper revision 1.1159.258.42 (4230e421NhFkCppVay5rDH0tzHn2bQ) Merge firebug.cl.cam.ac.uk:/auto/groups/xeno-xenod/BK/xen-2.0-testing.bk into firebug.cl.cam.ac.uk:/local/scratch/cl349/xen-2.0-testing.bk-2.6.11 --- ba3ece2d2e1312b9062b32ae249e662795a91f76 diff --cc .rootkeys index f5baebe00f,8e29f01aa4..46d3689876 --- a/.rootkeys +++ b/.rootkeys @@@ -128,135 -127,131 +128,133 @@@ 3e5a4e683HKVU-sxtagrDasRB8eBVw linux-2.4.29-xen-sparse/mm/swapfile.c 41180721bNns9Na7w1nJ0ZVt8bhUNA linux-2.4.29-xen-sparse/mm/vmalloc.c 41505c57WAd5l1rlfCLNSCpx9J13vA linux-2.4.29-xen-sparse/net/core/skbuff.c - 40f562372u3A7_kfbYYixPHJJxYUxA linux-2.6.10-xen-sparse/arch/xen/Kconfig - 40f56237utH41NPukqHksuNf29IC9A linux-2.6.10-xen-sparse/arch/xen/Kconfig.drivers - 40f56237penAAlWVBVDpeQZNFIg8CA linux-2.6.10-xen-sparse/arch/xen/Makefile - 40f56237JTc60m1FRlUxkUaGSQKrNw linux-2.6.10-xen-sparse/arch/xen/boot/Makefile - 40f56237hRxbacU_3PdoAl6DjZ3Jnw linux-2.6.10-xen-sparse/arch/xen/configs/xen0_defconfig - 40f56237wubfjJKlfIzZlI3ZM2VgGA linux-2.6.10-xen-sparse/arch/xen/configs/xenU_defconfig - 40f56237Mta0yHNaMS_qtM2rge0qYA linux-2.6.10-xen-sparse/arch/xen/i386/Kconfig - 40f56238u2CJdXNpjsZgHBxeVyY-2g linux-2.6.10-xen-sparse/arch/xen/i386/Makefile - 40f56238eczveJ86k_4hNxCLRQIF-g linux-2.6.10-xen-sparse/arch/xen/i386/kernel/Makefile - 40f56238rXVTJQKbBuXXLH52qEArcg linux-2.6.10-xen-sparse/arch/xen/i386/kernel/cpu/Makefile - 40f562385s4lr6Zg92gExe7UQ4A76Q linux-2.6.10-xen-sparse/arch/xen/i386/kernel/cpu/common.c - 41ab440bnpxZdWShZrGgM9pPaz5rmA linux-2.6.10-xen-sparse/arch/xen/i386/kernel/cpu/mtrr/Makefile - 41ab440bBKWz-aEOEojU4PAMXe3Ppg linux-2.6.10-xen-sparse/arch/xen/i386/kernel/cpu/mtrr/main.c - 40f56238XDtHSijkAFlbv1PT8Bhw_Q linux-2.6.10-xen-sparse/arch/xen/i386/kernel/entry.S - 40f56238bnvciAuyzAiMkdzGErYt1A linux-2.6.10-xen-sparse/arch/xen/i386/kernel/head.S - 40f58a0d31M2EkuPbG94ns_nOi0PVA linux-2.6.10-xen-sparse/arch/xen/i386/kernel/i386_ksyms.c - 40faa751_zbZlAmLyQgCXdYekVFdWA linux-2.6.10-xen-sparse/arch/xen/i386/kernel/ioport.c - 40f56238ue3YRsK52HG7iccNzP1AwQ linux-2.6.10-xen-sparse/arch/xen/i386/kernel/ldt.c - 41d54a76YMCA67S8J-TBT3J62Wx6yA linux-2.6.10-xen-sparse/arch/xen/i386/kernel/microcode.c - 4107adf1cNtsuOxOB4T6paAoY2R2PA linux-2.6.10-xen-sparse/arch/xen/i386/kernel/pci-dma.c - 40f56238a8iOVDEoostsbun_sy2i4g linux-2.6.10-xen-sparse/arch/xen/i386/kernel/process.c - 40f56238YQIJoYG2ehDGEcdTgLmGbg linux-2.6.10-xen-sparse/arch/xen/i386/kernel/setup.c - 40f56238nWMQg7CKbyTy0KJNvCzbtg linux-2.6.10-xen-sparse/arch/xen/i386/kernel/signal.c - 40f56238qVGkpO_ycnQA8k03kQzAgA linux-2.6.10-xen-sparse/arch/xen/i386/kernel/time.c - 40f56238NzTgeO63RGoxHrW5NQeO3Q linux-2.6.10-xen-sparse/arch/xen/i386/kernel/timers/Makefile - 40f56238BMqG5PuSHufpjbvp_helBw linux-2.6.10-xen-sparse/arch/xen/i386/kernel/timers/timer_tsc.c - 40f562389xNa78YBZciUibQjyRU_Lg linux-2.6.10-xen-sparse/arch/xen/i386/kernel/traps.c - 40f56238JypKAUG01ZojFwH7qnZ5uA linux-2.6.10-xen-sparse/arch/xen/i386/kernel/vsyscall.S - 40f56238wi6AdNQjm0RT57bSkwb6hg linux-2.6.10-xen-sparse/arch/xen/i386/kernel/vsyscall.lds - 40f56238a3w6-byOzexIlMgni76Lcg linux-2.6.10-xen-sparse/arch/xen/i386/mm/Makefile - 40f56238ILx8xlbywNbzTdv5Zr4xXQ linux-2.6.10-xen-sparse/arch/xen/i386/mm/fault.c - 4118cc35CbY8rfGVspF5O-7EkXBEAA linux-2.6.10-xen-sparse/arch/xen/i386/mm/highmem.c - 40f562383SKvDStdtrvzr5fyCbW4rw linux-2.6.10-xen-sparse/arch/xen/i386/mm/hypervisor.c - 40f56239xcNylAxuGsQHwi1AyMLV8w linux-2.6.10-xen-sparse/arch/xen/i386/mm/init.c - 41062ab7CjxC1UBaFhOMWWdhHkIUyg linux-2.6.10-xen-sparse/arch/xen/i386/mm/ioremap.c - 413b5ab8LIowAnQrEmaOJSdmqm96jQ linux-2.6.10-xen-sparse/arch/xen/i386/mm/pageattr.c - 40f5623906UYHv1rsVUeRc0tFT0dWw linux-2.6.10-xen-sparse/arch/xen/i386/mm/pgtable.c - 4107adf12ndy94MidCaivDibJ3pPAg linux-2.6.10-xen-sparse/arch/xen/i386/pci/Makefile - 4107adf1WcCgkhsdLTRGX52cOG1vJg linux-2.6.10-xen-sparse/arch/xen/i386/pci/direct.c - 4107adf1s5u6249DNPUViX1YNagbUQ linux-2.6.10-xen-sparse/arch/xen/i386/pci/irq.c - 40f56239zOksGg_H4XD4ye6iZNtoZA linux-2.6.10-xen-sparse/arch/xen/kernel/Makefile - 40f56239bvOjuuuViZ0XMlNiREFC0A linux-2.6.10-xen-sparse/arch/xen/kernel/ctrl_if.c - 41ab6fa06JdF7jxUsuDcjN3UhuIAxg linux-2.6.10-xen-sparse/arch/xen/kernel/devmem.c - 40f56238xFQe9T7M_U_FItM-bZIpLw linux-2.6.10-xen-sparse/arch/xen/kernel/evtchn.c - 4110f478aeQWllIN7J4kouAHiAqrPw linux-2.6.10-xen-sparse/arch/xen/kernel/fixup.c - 412dfae9eA3_6e6bCGUtg1mj8b56fQ linux-2.6.10-xen-sparse/arch/xen/kernel/gnttab.c - 40f562392LBhwmOxVPsYdkYXMxI_ZQ linux-2.6.10-xen-sparse/arch/xen/kernel/reboot.c - 414c113396tK1HTVeUalm3u-1DF16g linux-2.6.10-xen-sparse/arch/xen/kernel/skbuff.c - 3f68905c5eiA-lBMQSvXLMWS1ikDEA linux-2.6.10-xen-sparse/arch/xen/kernel/xen_proc.c - 41261688yS8eAyy-7kzG4KBs0xbYCA linux-2.6.10-xen-sparse/drivers/Makefile - 4108f5c1WfTIrs0HZFeV39sttekCTw linux-2.6.10-xen-sparse/drivers/char/mem.c - 4111308bZAIzwf_Kzu6x1TZYZ3E0_Q linux-2.6.10-xen-sparse/drivers/char/tty_io.c - 40f56239Dp_vMTgz8TEbvo1hjHGc3w linux-2.6.10-xen-sparse/drivers/xen/Makefile - 41768fbcncpBQf8s2l2-CwoSNIZ9uA linux-2.6.10-xen-sparse/drivers/xen/balloon/Makefile - 3e6377f8i5e9eGz7Pw6fQuhuTQ7DQg linux-2.6.10-xen-sparse/drivers/xen/balloon/balloon.c - 410d0893otFGghmv4dUXDUBBdY5aIA linux-2.6.10-xen-sparse/drivers/xen/blkback/Makefile - 4087cf0d1XgMkooTZAiJS6NrcpLQNQ linux-2.6.10-xen-sparse/drivers/xen/blkback/blkback.c - 4087cf0dZadZ8r6CEt4fNN350Yle3A linux-2.6.10-xen-sparse/drivers/xen/blkback/common.h - 4087cf0dxlh29iw0w-9rxOCEGCjPcw linux-2.6.10-xen-sparse/drivers/xen/blkback/control.c - 4087cf0dbuoH20fMjNZjcgrRK-1msQ linux-2.6.10-xen-sparse/drivers/xen/blkback/interface.c - 4087cf0dk97tacDzxfByWV7JifUYqA linux-2.6.10-xen-sparse/drivers/xen/blkback/vbd.c - 40f56239Sfle6wGv5FS0wjS_HI150A linux-2.6.10-xen-sparse/drivers/xen/blkfront/Kconfig - 40f562395atl9x4suKGhPkjqLOXESg linux-2.6.10-xen-sparse/drivers/xen/blkfront/Makefile - 40f56239-JNIaTzlviVJohVdoYOUpw linux-2.6.10-xen-sparse/drivers/xen/blkfront/blkfront.c - 40f56239y9naBTXe40Pi2J_z3p-d1g linux-2.6.10-xen-sparse/drivers/xen/blkfront/block.h - 40f56239BVfPsXBiWQitXgDRtOsiqg linux-2.6.10-xen-sparse/drivers/xen/blkfront/vbd.c - 40f56239fsLjvtD8YBRAWphps4FDjg linux-2.6.10-xen-sparse/drivers/xen/console/Makefile - 3e5a4e651TH-SXHoufurnWjgl5bfOA linux-2.6.10-xen-sparse/drivers/xen/console/console.c - 40f56239KYxO0YabhPzCTeUuln-lnA linux-2.6.10-xen-sparse/drivers/xen/evtchn/Makefile - 40f56239DoibTX6R-ZYd3QTXAB8_TA linux-2.6.10-xen-sparse/drivers/xen/evtchn/evtchn.c - 410a9817HEVJvred5Oy_uKH3HFJC5Q linux-2.6.10-xen-sparse/drivers/xen/netback/Makefile - 4097ba831lpGeLlPg-bfV8XarVVuoQ linux-2.6.10-xen-sparse/drivers/xen/netback/common.h - 4097ba83wvv8yi5P5xugCUBAdb6O-A linux-2.6.10-xen-sparse/drivers/xen/netback/control.c - 4097ba83byY5bTSugJGZ1exTxIcMKw linux-2.6.10-xen-sparse/drivers/xen/netback/interface.c - 4087cf0dGmSbFhFZyIZBJzvqxY-qBw linux-2.6.10-xen-sparse/drivers/xen/netback/netback.c - 40f56239lrg_Ob0BJ8WBFS1zeg2CYw linux-2.6.10-xen-sparse/drivers/xen/netfront/Kconfig - 40f56239Wd4k_ycG_mFsSO1r5xKdtQ linux-2.6.10-xen-sparse/drivers/xen/netfront/Makefile - 405853f6nbeazrNyEWNHBuoSg2PiPA linux-2.6.10-xen-sparse/drivers/xen/netfront/netfront.c - 4108f5c1ppFXVpQzCOAZ6xXYubsjKA linux-2.6.10-xen-sparse/drivers/xen/privcmd/Makefile - 3e5a4e65IUfzzMu2kZFlGEB8-rpTaA linux-2.6.10-xen-sparse/drivers/xen/privcmd/privcmd.c - 412f47e4RKD-R5IS5gEXvcT8L4v8gA linux-2.6.10-xen-sparse/include/asm-generic/pgtable.h - 40f56239YAjS52QG2FIAQpHDZAdGHg linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/desc.h - 4107adf1E5O4ztGHNGMzCCNhcvqNow linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/dma-mapping.h - 40f5623akIoBsQ3KxSB2kufkbgONXQ linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/fixmap.h - 41979925z1MsKU1SfuuheM1IFDQ_bA linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/floppy.h - 4118b6a418gnL6AZsTdglC92YGqYTg linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/highmem.h - 40f5623aJVXQwpJMOLE99XgvGsfQ8Q linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/io.h - 40f5623aKXkBBxgpLx2NcvkncQ1Yyw linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/mach-xen/irq_vectors.h - 40f5623aDMCsWOFO0jktZ4e8sjwvEg linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/mach-xen/setup_arch_post.h - 40f5623arsFXkGdPvIqvFi3yFXGR0Q linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/mach-xen/setup_arch_pre.h - 4120f807GCO0uqsLqdZj9csxR1Wthw linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/mmu_context.h - 40f5623aFTyFTR-vdiA-KaGxk5JOKQ linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/msr.h - 40f5623adgjZq9nAgCt0IXdWl7udSA linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/page.h - 40f5623a54NuG-7qHihGYmw4wWQnMA linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/param.h - 41137cc1kkvg0cg7uxddcEfjL7L67w linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/pci.h - 40f5623atCokYc2uCysSJ8jFO8TEsw linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/pgalloc.h - 412e01beTwiaC8sYY4XJP8PxLST5CA linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/pgtable-2level-defs.h - 40f5623aEToIXouJgO-ao5d5pcEt1w linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/pgtable-2level.h - 40f5623aCCXRPlGpNthVXstGz9ZV3A linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/pgtable.h - 40f5623aPCkQQfPtJSooGdhcatrvnQ linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/processor.h - 412ea0afQL2CAI-f522TbLjLPMibPQ linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/ptrace.h - 40f5623bzLvxr7WoJIxVf2OH4rCBJg linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/segment.h - 40f5623bG_LzgG6-qwk292nTc5Wabw linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/setup.h - 40f5623bgzm_9vwxpzJswlAxg298Gg linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/synch_bitops.h - 40f5623bVdKP7Dt7qm8twu3NcnGNbA linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/system.h - 40f5623bc8LKPRO09wY5dGDnY_YCpw linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/tlbflush.h - 41062ab7uFxnCq-KtPeAm-aV8CicgA linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/vga.h - 40f5623bxUbeGjkRrjDguCy_Gm8RLw linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/xor.h - 41af4017PDMuSmMWtSRU5UC9Vylw5g linux-2.6.10-xen-sparse/include/asm-xen/balloon.h - 40f5623bYNP7tHE2zX6YQxp9Zq2utQ linux-2.6.10-xen-sparse/include/asm-xen/ctrl_if.h - 40f5623b3Eqs8pAc5WpPX8_jTzV2qw linux-2.6.10-xen-sparse/include/asm-xen/evtchn.h - 419b4e9367PjTEvdjwavWN12BeBBXg linux-2.6.10-xen-sparse/include/asm-xen/foreign_page.h - 412dfaeazclyNDM0cpnp60Yo4xulpQ linux-2.6.10-xen-sparse/include/asm-xen/gnttab.h - 40f5623aGPlsm0u1LTO-NVZ6AGzNRQ linux-2.6.10-xen-sparse/include/asm-xen/hypervisor.h - 3f108af1ylCIm82H052FVTfXACBHrw linux-2.6.10-xen-sparse/include/asm-xen/linux-public/privcmd.h - 3fa8e3f0kBLeE4To2vpdi3cpJbIkbQ linux-2.6.10-xen-sparse/include/asm-xen/linux-public/suspend.h - 40f5623cndVUFlkxpf7Lfx7xu8madQ linux-2.6.10-xen-sparse/include/asm-xen/multicall.h - 4122466356eIBnC9ot44WSVVIFyhQA linux-2.6.10-xen-sparse/include/asm-xen/queues.h - 3f689063BoW-HWV3auUJ-OqXfcGArw linux-2.6.10-xen-sparse/include/asm-xen/xen_proc.h - 419b4e93z2S0gR17XTy8wg09JEwAhg linux-2.6.10-xen-sparse/include/linux/gfp.h +42305f545Vc5SLCUewZ2-n-P9JJhEQ linux-2.6.10-xen-sparse/include/linux/highmem.h - 419dfc609zbti8rqL60tL2dHXQ_rvQ linux-2.6.10-xen-sparse/include/linux/irq.h - 4124f66f4NaKNa0xPiGGykn9QaZk3w linux-2.6.10-xen-sparse/include/linux/skbuff.h - 419dfc6awx7w88wk6cG9P3mPidX6LQ linux-2.6.10-xen-sparse/kernel/irq/manage.c - 40f56a0ddHCSs3501MY4hRf22tctOw linux-2.6.10-xen-sparse/mkbuildtree +42305f54Q6xJ1bXcQJlCQq1m-e2C8g linux-2.6.10-xen-sparse/mm/highmem.c - 412f46c0LJuKAgSPGoC0Z1DEkLfuLA linux-2.6.10-xen-sparse/mm/memory.c - 410a94a4KT6I6X0LVc7djB39tRDp4g linux-2.6.10-xen-sparse/mm/page_alloc.c - 41505c572m-s9ATiO1LiD1GPznTTIg linux-2.6.10-xen-sparse/net/core/skbuff.c + 40f562372u3A7_kfbYYixPHJJxYUxA linux-2.6.11-xen-sparse/arch/xen/Kconfig + 40f56237utH41NPukqHksuNf29IC9A linux-2.6.11-xen-sparse/arch/xen/Kconfig.drivers + 40f56237penAAlWVBVDpeQZNFIg8CA linux-2.6.11-xen-sparse/arch/xen/Makefile + 40f56237JTc60m1FRlUxkUaGSQKrNw linux-2.6.11-xen-sparse/arch/xen/boot/Makefile + 40f56237hRxbacU_3PdoAl6DjZ3Jnw linux-2.6.11-xen-sparse/arch/xen/configs/xen0_defconfig + 40f56237wubfjJKlfIzZlI3ZM2VgGA linux-2.6.11-xen-sparse/arch/xen/configs/xenU_defconfig + 40f56237Mta0yHNaMS_qtM2rge0qYA linux-2.6.11-xen-sparse/arch/xen/i386/Kconfig + 40f56238u2CJdXNpjsZgHBxeVyY-2g linux-2.6.11-xen-sparse/arch/xen/i386/Makefile + 40f56238eczveJ86k_4hNxCLRQIF-g linux-2.6.11-xen-sparse/arch/xen/i386/kernel/Makefile + 40f56238rXVTJQKbBuXXLH52qEArcg linux-2.6.11-xen-sparse/arch/xen/i386/kernel/cpu/Makefile + 40f562385s4lr6Zg92gExe7UQ4A76Q linux-2.6.11-xen-sparse/arch/xen/i386/kernel/cpu/common.c + 41ab440bnpxZdWShZrGgM9pPaz5rmA linux-2.6.11-xen-sparse/arch/xen/i386/kernel/cpu/mtrr/Makefile + 41ab440bBKWz-aEOEojU4PAMXe3Ppg linux-2.6.11-xen-sparse/arch/xen/i386/kernel/cpu/mtrr/main.c + 40f56238XDtHSijkAFlbv1PT8Bhw_Q linux-2.6.11-xen-sparse/arch/xen/i386/kernel/entry.S + 40f56238bnvciAuyzAiMkdzGErYt1A linux-2.6.11-xen-sparse/arch/xen/i386/kernel/head.S + 40f58a0d31M2EkuPbG94ns_nOi0PVA linux-2.6.11-xen-sparse/arch/xen/i386/kernel/i386_ksyms.c + 40faa751_zbZlAmLyQgCXdYekVFdWA linux-2.6.11-xen-sparse/arch/xen/i386/kernel/ioport.c + 40f56238ue3YRsK52HG7iccNzP1AwQ linux-2.6.11-xen-sparse/arch/xen/i386/kernel/ldt.c + 41d54a76YMCA67S8J-TBT3J62Wx6yA linux-2.6.11-xen-sparse/arch/xen/i386/kernel/microcode.c + 4107adf1cNtsuOxOB4T6paAoY2R2PA linux-2.6.11-xen-sparse/arch/xen/i386/kernel/pci-dma.c + 40f56238a8iOVDEoostsbun_sy2i4g linux-2.6.11-xen-sparse/arch/xen/i386/kernel/process.c + 40f56238YQIJoYG2ehDGEcdTgLmGbg linux-2.6.11-xen-sparse/arch/xen/i386/kernel/setup.c + 40f56238nWMQg7CKbyTy0KJNvCzbtg linux-2.6.11-xen-sparse/arch/xen/i386/kernel/signal.c + 40f56238qVGkpO_ycnQA8k03kQzAgA linux-2.6.11-xen-sparse/arch/xen/i386/kernel/time.c + 40f56238NzTgeO63RGoxHrW5NQeO3Q linux-2.6.11-xen-sparse/arch/xen/i386/kernel/timers/Makefile + 40f56238BMqG5PuSHufpjbvp_helBw linux-2.6.11-xen-sparse/arch/xen/i386/kernel/timers/timer_tsc.c + 40f562389xNa78YBZciUibQjyRU_Lg linux-2.6.11-xen-sparse/arch/xen/i386/kernel/traps.c + 40f56238JypKAUG01ZojFwH7qnZ5uA linux-2.6.11-xen-sparse/arch/xen/i386/kernel/vsyscall.S + 40f56238wi6AdNQjm0RT57bSkwb6hg linux-2.6.11-xen-sparse/arch/xen/i386/kernel/vsyscall.lds + 40f56238a3w6-byOzexIlMgni76Lcg linux-2.6.11-xen-sparse/arch/xen/i386/mm/Makefile + 40f56238ILx8xlbywNbzTdv5Zr4xXQ linux-2.6.11-xen-sparse/arch/xen/i386/mm/fault.c + 4118cc35CbY8rfGVspF5O-7EkXBEAA linux-2.6.11-xen-sparse/arch/xen/i386/mm/highmem.c + 40f562383SKvDStdtrvzr5fyCbW4rw linux-2.6.11-xen-sparse/arch/xen/i386/mm/hypervisor.c + 40f56239xcNylAxuGsQHwi1AyMLV8w linux-2.6.11-xen-sparse/arch/xen/i386/mm/init.c + 41062ab7CjxC1UBaFhOMWWdhHkIUyg linux-2.6.11-xen-sparse/arch/xen/i386/mm/ioremap.c + 413b5ab8LIowAnQrEmaOJSdmqm96jQ linux-2.6.11-xen-sparse/arch/xen/i386/mm/pageattr.c + 40f5623906UYHv1rsVUeRc0tFT0dWw linux-2.6.11-xen-sparse/arch/xen/i386/mm/pgtable.c + 4107adf12ndy94MidCaivDibJ3pPAg linux-2.6.11-xen-sparse/arch/xen/i386/pci/Makefile + 4107adf1WcCgkhsdLTRGX52cOG1vJg linux-2.6.11-xen-sparse/arch/xen/i386/pci/direct.c + 4107adf1s5u6249DNPUViX1YNagbUQ linux-2.6.11-xen-sparse/arch/xen/i386/pci/irq.c + 40f56239zOksGg_H4XD4ye6iZNtoZA linux-2.6.11-xen-sparse/arch/xen/kernel/Makefile + 40f56239bvOjuuuViZ0XMlNiREFC0A linux-2.6.11-xen-sparse/arch/xen/kernel/ctrl_if.c + 41ab6fa06JdF7jxUsuDcjN3UhuIAxg linux-2.6.11-xen-sparse/arch/xen/kernel/devmem.c + 40f56238xFQe9T7M_U_FItM-bZIpLw linux-2.6.11-xen-sparse/arch/xen/kernel/evtchn.c + 4110f478aeQWllIN7J4kouAHiAqrPw linux-2.6.11-xen-sparse/arch/xen/kernel/fixup.c + 412dfae9eA3_6e6bCGUtg1mj8b56fQ linux-2.6.11-xen-sparse/arch/xen/kernel/gnttab.c + 40f562392LBhwmOxVPsYdkYXMxI_ZQ linux-2.6.11-xen-sparse/arch/xen/kernel/reboot.c + 414c113396tK1HTVeUalm3u-1DF16g linux-2.6.11-xen-sparse/arch/xen/kernel/skbuff.c + 3f68905c5eiA-lBMQSvXLMWS1ikDEA linux-2.6.11-xen-sparse/arch/xen/kernel/xen_proc.c + 41261688yS8eAyy-7kzG4KBs0xbYCA linux-2.6.11-xen-sparse/drivers/Makefile + 4108f5c1WfTIrs0HZFeV39sttekCTw linux-2.6.11-xen-sparse/drivers/char/mem.c + 4111308bZAIzwf_Kzu6x1TZYZ3E0_Q linux-2.6.11-xen-sparse/drivers/char/tty_io.c + 40f56239Dp_vMTgz8TEbvo1hjHGc3w linux-2.6.11-xen-sparse/drivers/xen/Makefile + 41768fbcncpBQf8s2l2-CwoSNIZ9uA linux-2.6.11-xen-sparse/drivers/xen/balloon/Makefile + 3e6377f8i5e9eGz7Pw6fQuhuTQ7DQg linux-2.6.11-xen-sparse/drivers/xen/balloon/balloon.c + 410d0893otFGghmv4dUXDUBBdY5aIA linux-2.6.11-xen-sparse/drivers/xen/blkback/Makefile + 4087cf0d1XgMkooTZAiJS6NrcpLQNQ linux-2.6.11-xen-sparse/drivers/xen/blkback/blkback.c + 4087cf0dZadZ8r6CEt4fNN350Yle3A linux-2.6.11-xen-sparse/drivers/xen/blkback/common.h + 4087cf0dxlh29iw0w-9rxOCEGCjPcw linux-2.6.11-xen-sparse/drivers/xen/blkback/control.c + 4087cf0dbuoH20fMjNZjcgrRK-1msQ linux-2.6.11-xen-sparse/drivers/xen/blkback/interface.c + 4087cf0dk97tacDzxfByWV7JifUYqA linux-2.6.11-xen-sparse/drivers/xen/blkback/vbd.c + 40f56239Sfle6wGv5FS0wjS_HI150A linux-2.6.11-xen-sparse/drivers/xen/blkfront/Kconfig + 40f562395atl9x4suKGhPkjqLOXESg linux-2.6.11-xen-sparse/drivers/xen/blkfront/Makefile + 40f56239-JNIaTzlviVJohVdoYOUpw linux-2.6.11-xen-sparse/drivers/xen/blkfront/blkfront.c + 40f56239y9naBTXe40Pi2J_z3p-d1g linux-2.6.11-xen-sparse/drivers/xen/blkfront/block.h + 40f56239BVfPsXBiWQitXgDRtOsiqg linux-2.6.11-xen-sparse/drivers/xen/blkfront/vbd.c + 40f56239fsLjvtD8YBRAWphps4FDjg linux-2.6.11-xen-sparse/drivers/xen/console/Makefile + 3e5a4e651TH-SXHoufurnWjgl5bfOA linux-2.6.11-xen-sparse/drivers/xen/console/console.c + 40f56239KYxO0YabhPzCTeUuln-lnA linux-2.6.11-xen-sparse/drivers/xen/evtchn/Makefile + 40f56239DoibTX6R-ZYd3QTXAB8_TA linux-2.6.11-xen-sparse/drivers/xen/evtchn/evtchn.c + 410a9817HEVJvred5Oy_uKH3HFJC5Q linux-2.6.11-xen-sparse/drivers/xen/netback/Makefile + 4097ba831lpGeLlPg-bfV8XarVVuoQ linux-2.6.11-xen-sparse/drivers/xen/netback/common.h + 4097ba83wvv8yi5P5xugCUBAdb6O-A linux-2.6.11-xen-sparse/drivers/xen/netback/control.c + 4097ba83byY5bTSugJGZ1exTxIcMKw linux-2.6.11-xen-sparse/drivers/xen/netback/interface.c + 4087cf0dGmSbFhFZyIZBJzvqxY-qBw linux-2.6.11-xen-sparse/drivers/xen/netback/netback.c + 40f56239lrg_Ob0BJ8WBFS1zeg2CYw linux-2.6.11-xen-sparse/drivers/xen/netfront/Kconfig + 40f56239Wd4k_ycG_mFsSO1r5xKdtQ linux-2.6.11-xen-sparse/drivers/xen/netfront/Makefile + 405853f6nbeazrNyEWNHBuoSg2PiPA linux-2.6.11-xen-sparse/drivers/xen/netfront/netfront.c + 4108f5c1ppFXVpQzCOAZ6xXYubsjKA linux-2.6.11-xen-sparse/drivers/xen/privcmd/Makefile + 3e5a4e65IUfzzMu2kZFlGEB8-rpTaA linux-2.6.11-xen-sparse/drivers/xen/privcmd/privcmd.c + 412f47e4RKD-R5IS5gEXvcT8L4v8gA linux-2.6.11-xen-sparse/include/asm-generic/pgtable.h + 40f56239YAjS52QG2FIAQpHDZAdGHg linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/desc.h + 4107adf1E5O4ztGHNGMzCCNhcvqNow linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/dma-mapping.h + 40f5623akIoBsQ3KxSB2kufkbgONXQ linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/fixmap.h + 41979925z1MsKU1SfuuheM1IFDQ_bA linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/floppy.h + 4118b6a418gnL6AZsTdglC92YGqYTg linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/highmem.h + 40f5623aJVXQwpJMOLE99XgvGsfQ8Q linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/io.h + 40f5623aKXkBBxgpLx2NcvkncQ1Yyw linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/mach-xen/irq_vectors.h + 40f5623aDMCsWOFO0jktZ4e8sjwvEg linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/mach-xen/setup_arch_post.h + 40f5623arsFXkGdPvIqvFi3yFXGR0Q linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/mach-xen/setup_arch_pre.h + 4120f807GCO0uqsLqdZj9csxR1Wthw linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/mmu_context.h + 40f5623aFTyFTR-vdiA-KaGxk5JOKQ linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/msr.h + 40f5623adgjZq9nAgCt0IXdWl7udSA linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/page.h + 40f5623a54NuG-7qHihGYmw4wWQnMA linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/param.h + 41137cc1kkvg0cg7uxddcEfjL7L67w linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/pci.h + 40f5623atCokYc2uCysSJ8jFO8TEsw linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/pgalloc.h + 412e01beTwiaC8sYY4XJP8PxLST5CA linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/pgtable-2level-defs.h + 40f5623aEToIXouJgO-ao5d5pcEt1w linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/pgtable-2level.h + 40f5623aCCXRPlGpNthVXstGz9ZV3A linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/pgtable.h + 40f5623aPCkQQfPtJSooGdhcatrvnQ linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/processor.h + 412ea0afQL2CAI-f522TbLjLPMibPQ linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/ptrace.h + 40f5623bzLvxr7WoJIxVf2OH4rCBJg linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/segment.h + 40f5623bG_LzgG6-qwk292nTc5Wabw linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/setup.h + 40f5623bgzm_9vwxpzJswlAxg298Gg linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/synch_bitops.h + 40f5623bVdKP7Dt7qm8twu3NcnGNbA linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/system.h + 40f5623bc8LKPRO09wY5dGDnY_YCpw linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/tlbflush.h + 41062ab7uFxnCq-KtPeAm-aV8CicgA linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/vga.h + 40f5623bxUbeGjkRrjDguCy_Gm8RLw linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/xor.h + 41af4017PDMuSmMWtSRU5UC9Vylw5g linux-2.6.11-xen-sparse/include/asm-xen/balloon.h + 40f5623bYNP7tHE2zX6YQxp9Zq2utQ linux-2.6.11-xen-sparse/include/asm-xen/ctrl_if.h + 40f5623b3Eqs8pAc5WpPX8_jTzV2qw linux-2.6.11-xen-sparse/include/asm-xen/evtchn.h + 419b4e9367PjTEvdjwavWN12BeBBXg linux-2.6.11-xen-sparse/include/asm-xen/foreign_page.h + 412dfaeazclyNDM0cpnp60Yo4xulpQ linux-2.6.11-xen-sparse/include/asm-xen/gnttab.h + 40f5623aGPlsm0u1LTO-NVZ6AGzNRQ linux-2.6.11-xen-sparse/include/asm-xen/hypervisor.h + 3f108af1ylCIm82H052FVTfXACBHrw linux-2.6.11-xen-sparse/include/asm-xen/linux-public/privcmd.h + 3fa8e3f0kBLeE4To2vpdi3cpJbIkbQ linux-2.6.11-xen-sparse/include/asm-xen/linux-public/suspend.h + 40f5623cndVUFlkxpf7Lfx7xu8madQ linux-2.6.11-xen-sparse/include/asm-xen/multicall.h + 4122466356eIBnC9ot44WSVVIFyhQA linux-2.6.11-xen-sparse/include/asm-xen/queues.h + 3f689063BoW-HWV3auUJ-OqXfcGArw linux-2.6.11-xen-sparse/include/asm-xen/xen_proc.h + 419b4e93z2S0gR17XTy8wg09JEwAhg linux-2.6.11-xen-sparse/include/linux/gfp.h + 419dfc609zbti8rqL60tL2dHXQ_rvQ linux-2.6.11-xen-sparse/include/linux/irq.h + 419dfc6awx7w88wk6cG9P3mPidX6LQ linux-2.6.11-xen-sparse/kernel/irq/manage.c + 40f56a0ddHCSs3501MY4hRf22tctOw linux-2.6.11-xen-sparse/mkbuildtree + 412f46c0LJuKAgSPGoC0Z1DEkLfuLA linux-2.6.11-xen-sparse/mm/memory.c + 410a94a4KT6I6X0LVc7djB39tRDp4g linux-2.6.11-xen-sparse/mm/page_alloc.c 413cb1e4zst25MDYjg63Y-NGC5_pLg netbsd-2.0-xen-sparse/Makefile 413cb1e5c_Mkxf_X0zimEhTKI_l4DA netbsd-2.0-xen-sparse/mkbuildtree 413cb1e5kY_Zil7-b0kI6hvCIxBEYg netbsd-2.0-xen-sparse/nbconfig-xen diff --cc linux-2.6.11-xen-sparse/drivers/xen/balloon/balloon.c index 0000000000,ee725d3d9d..6909fabaa7 mode 000000,100644..100644 --- a/linux-2.6.11-xen-sparse/drivers/xen/balloon/balloon.c +++ b/linux-2.6.11-xen-sparse/drivers/xen/balloon/balloon.c @@@ -1,0 -1,445 +1,454 @@@ + /****************************************************************************** + * balloon.c + * + * Xen balloon driver - enables returning/claiming memory to/from Xen. + * + * Copyright (c) 2003, B Dragovic + * Copyright (c) 2003-2004, M Williamson, K Fraser + * + * This file may be distributed separately from the Linux kernel, or + * incorporated into other software packages, subject to the following license: + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this source file (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + + static struct proc_dir_entry *balloon_pde; + + static DECLARE_MUTEX(balloon_mutex); + spinlock_t balloon_lock = SPIN_LOCK_UNLOCKED; + + /* We aim for 'current allocation' == 'target allocation'. */ + static unsigned long current_pages; + static unsigned long target_pages; + + /* We may hit the hard limit in Xen. If we do then we remember it. */ + static unsigned long hard_limit; + + /* + * Drivers may alter the memory reservation independently, but they must + * inform the balloon driver so that we can avoid hitting the hard limit. + */ + static unsigned long driver_pages; + + /* List of ballooned pages, threaded through the mem_map array. */ + static LIST_HEAD(ballooned_pages); + static unsigned long balloon_low, balloon_high; + + /* Main work function, always executed in process context. */ + static void balloon_process(void *unused); + static DECLARE_WORK(balloon_worker, balloon_process, NULL); + static struct timer_list balloon_timer; + + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + /* Use the private and mapping fields of struct page as a list. */ + #define PAGE_TO_LIST(p) ( (struct list_head *)&p->private ) + #define LIST_TO_PAGE(l) ( list_entry( ((unsigned long *)l), \ + struct page, private ) ) + #define UNLIST_PAGE(p) do { list_del(PAGE_TO_LIST(p)); \ + p->mapping = NULL; \ + p->private = 0; } while(0) + #else + /* There's a dedicated list field in struct page we can use. */ + #define PAGE_TO_LIST(p) ( &p->list ) + #define LIST_TO_PAGE(l) ( list_entry(l, struct page, list) ) + #define UNLIST_PAGE(p) ( list_del(&p->list) ) + #define pte_offset_kernel pte_offset + #define subsys_initcall(_fn) __initcall(_fn) ++#define pfn_to_page(_pfn) (mem_map + (_pfn)) + #endif + + #define IPRINTK(fmt, args...) \ + printk(KERN_INFO "xen_mem: " fmt, ##args) + #define WPRINTK(fmt, args...) \ + printk(KERN_WARNING "xen_mem: " fmt, ##args) + + /* balloon_append: add the given page to the balloon. */ + static void balloon_append(struct page *page) + { + /* Low memory is re-populated first, so highmem pages go at list tail. */ + if ( PageHighMem(page) ) + { + list_add_tail(PAGE_TO_LIST(page), &ballooned_pages); + balloon_high++; + } + else + { + list_add(PAGE_TO_LIST(page), &ballooned_pages); + balloon_low++; + } + } + + /* balloon_retrieve: rescue a page from the balloon, if it is not empty. */ + static struct page *balloon_retrieve(void) + { + struct page *page; + + if ( list_empty(&ballooned_pages) ) + return NULL; + + page = LIST_TO_PAGE(ballooned_pages.next); + UNLIST_PAGE(page); + + if ( PageHighMem(page) ) + balloon_high--; + else + balloon_low--; + + return page; + } + + static inline pte_t *get_ptep(unsigned long addr) + { + pgd_t *pgd; + pud_t *pud; + pmd_t *pmd; + + pgd = pgd_offset_k(addr); + if ( pgd_none(*pgd) || pgd_bad(*pgd) ) BUG(); + + pud = pud_offset(pgd, addr); + if ( pud_none(*pud) || pud_bad(*pud) ) BUG(); + + pmd = pmd_offset(pud, addr); + if ( pmd_none(*pmd) || pmd_bad(*pmd) ) BUG(); + + return pte_offset_kernel(pmd, addr); + } + + static void balloon_alarm(unsigned long unused) + { + schedule_work(&balloon_worker); + } + + static unsigned long current_target(void) + { + unsigned long target = min(target_pages, hard_limit); + if ( target > (current_pages + balloon_low + balloon_high) ) + target = current_pages + balloon_low + balloon_high; + return target; + } + + /* + * We avoid multiple worker processes conflicting via the balloon mutex. + * We may of course race updates of the target counts (which are protected + * by the balloon lock), or with changes to the Xen hard limit, but we will + * recover from these in time. + */ + static void balloon_process(void *unused) + { + unsigned long *mfn_list, pfn, i, flags; + struct page *page; + long credit, debt, rc; + void *v; + + down(&balloon_mutex); + + retry: + mfn_list = NULL; + + if ( (credit = current_target() - current_pages) > 0 ) + { + mfn_list = (unsigned long *)vmalloc(credit * sizeof(*mfn_list)); + if ( mfn_list == NULL ) + goto out; + + balloon_lock(flags); + rc = HYPERVISOR_dom_mem_op( + MEMOP_increase_reservation, mfn_list, credit, 0); + balloon_unlock(flags); + if ( rc < credit ) + { + /* We hit the Xen hard limit: reprobe. */ + if ( HYPERVISOR_dom_mem_op( + MEMOP_decrease_reservation, mfn_list, rc, 0) != rc ) + BUG(); + hard_limit = current_pages + rc - driver_pages; + vfree(mfn_list); + goto retry; + } + + for ( i = 0; i < credit; i++ ) + { + if ( (page = balloon_retrieve()) == NULL ) + BUG(); + + pfn = page - mem_map; + if ( phys_to_machine_mapping[pfn] != INVALID_P2M_ENTRY ) + BUG(); + + /* Update P->M and M->P tables. */ + phys_to_machine_mapping[pfn] = mfn_list[i]; + queue_machphys_update(mfn_list[i], pfn); + + /* Link back into the page tables if it's not a highmem page. */ + if ( pfn < max_low_pfn ) + queue_l1_entry_update( + get_ptep((unsigned long)__va(pfn << PAGE_SHIFT)), + (mfn_list[i] << PAGE_SHIFT) | pgprot_val(PAGE_KERNEL)); + + /* Finally, relinquish the memory back to the system allocator. */ + ClearPageReserved(page); + set_page_count(page, 1); + __free_page(page); + } + + current_pages += credit; + } + else if ( credit < 0 ) + { + debt = -credit; + + mfn_list = (unsigned long *)vmalloc(debt * sizeof(*mfn_list)); + if ( mfn_list == NULL ) + goto out; + + for ( i = 0; i < debt; i++ ) + { + if ( (page = alloc_page(GFP_HIGHUSER)) == NULL ) + { + debt = i; + break; + } + + pfn = page - mem_map; + mfn_list[i] = phys_to_machine_mapping[pfn]; - phys_to_machine_mapping[pfn] = INVALID_P2M_ENTRY; + + if ( !PageHighMem(page) ) + { - v = phys_to_virt((page - mem_map) << PAGE_SHIFT); ++ v = phys_to_virt(pfn << PAGE_SHIFT); + scrub_pages(v, 1); + queue_l1_entry_update(get_ptep((unsigned long)v), 0); + } + #ifdef CONFIG_XEN_SCRUB_PAGES + else + { + v = kmap(page); + scrub_pages(v, 1); + kunmap(page); + } -#endif - - balloon_append(page); ++#endif + } + ++ /* Ensure that ballooned highmem pages don't have cached mappings. */ ++ kmap_flush_unused(); ++ + /* Flush updates through and flush the TLB. */ + xen_tlb_flush(); + ++ /* No more mappings: invalidate pages in P2M and add to balloon. */ ++ for ( i = 0; i < debt; i++ ) ++ { ++ pfn = mfn_to_pfn(mfn_list[i]); ++ phys_to_machine_mapping[pfn] = INVALID_P2M_ENTRY; ++ balloon_append(pfn_to_page(pfn)); ++ } ++ + if ( HYPERVISOR_dom_mem_op( + MEMOP_decrease_reservation, mfn_list, debt, 0) != debt ) + BUG(); + + current_pages -= debt; + } + + out: + if ( mfn_list != NULL ) + vfree(mfn_list); + + /* Schedule more work if there is some still to be done. */ + if ( current_target() != current_pages ) + mod_timer(&balloon_timer, jiffies + HZ); + + up(&balloon_mutex); + } + + /* Resets the Xen limit, sets new target, and kicks off processing. */ + static void set_new_target(unsigned long target) + { + /* No need for lock. Not read-modify-write updates. */ + hard_limit = ~0UL; + target_pages = target; + schedule_work(&balloon_worker); + } + + static void balloon_ctrlif_rx(ctrl_msg_t *msg, unsigned long id) + { + switch ( msg->subtype ) + { + case CMSG_MEM_REQUEST_SET: + { + mem_request_t *req = (mem_request_t *)&msg->msg[0]; + if ( msg->length != sizeof(mem_request_t) ) + goto parse_error; + set_new_target(req->target); + req->status = 0; + } + break; + default: + goto parse_error; + } + + ctrl_if_send_response(msg); + return; + + parse_error: + msg->length = 0; + ctrl_if_send_response(msg); + } + + static int balloon_write(struct file *file, const char __user *buffer, + unsigned long count, void *data) + { + char memstring[64], *endchar; + unsigned long long target_bytes; + + if ( !capable(CAP_SYS_ADMIN) ) + return -EPERM; + + if ( count <= 1 ) + return -EBADMSG; /* runt */ + if ( count > sizeof(memstring) ) + return -EFBIG; /* too long */ + + if ( copy_from_user(memstring, buffer, count) ) + return -EFAULT; + memstring[sizeof(memstring)-1] = '\0'; + + target_bytes = memparse(memstring, &endchar); + set_new_target(target_bytes >> PAGE_SHIFT); + + return count; + } + + static int balloon_read(char *page, char **start, off_t off, + int count, int *eof, void *data) + { + int len; + + #define K(_p) ((_p)<<(PAGE_SHIFT-10)) + len = sprintf( + page, + "Current allocation: %8lu kB\n" + "Requested target: %8lu kB\n" + "Low-mem balloon: %8lu kB\n" + "High-mem balloon: %8lu kB\n" + "Xen hard limit: ", + K(current_pages), K(target_pages), K(balloon_low), K(balloon_high)); + + if ( hard_limit != ~0UL ) + len += sprintf( + page + len, + "%8lu kB (inc. %8lu kB driver headroom)\n", + K(hard_limit), K(driver_pages)); + else + len += sprintf( + page + len, + " ??? kB\n"); + + *eof = 1; + return len; + } + + static int __init balloon_init(void) + { + unsigned long pfn; + struct page *page; + + IPRINTK("Initialising balloon driver.\n"); + + current_pages = min(xen_start_info.nr_pages, max_pfn); + target_pages = current_pages; + balloon_low = 0; + balloon_high = 0; + driver_pages = 0UL; + hard_limit = ~0UL; + + init_timer(&balloon_timer); + balloon_timer.data = 0; + balloon_timer.function = balloon_alarm; + + if ( (balloon_pde = create_xen_proc_entry("balloon", 0644)) == NULL ) + { + WPRINTK("Unable to create /proc/xen/balloon.\n"); + return -1; + } + + balloon_pde->read_proc = balloon_read; + balloon_pde->write_proc = balloon_write; + + (void)ctrl_if_register_receiver(CMSG_MEM_REQUEST, balloon_ctrlif_rx, 0); + + /* Initialise the balloon with excess memory space. */ + for ( pfn = xen_start_info.nr_pages; pfn < max_pfn; pfn++ ) + { + page = &mem_map[pfn]; + if ( !PageReserved(page) ) + balloon_append(page); + } + + return 0; + } + + subsys_initcall(balloon_init); + + void balloon_update_driver_allowance(long delta) + { + unsigned long flags; + balloon_lock(flags); + driver_pages += delta; /* non-atomic update */ + balloon_unlock(flags); + } + + void balloon_put_pages(unsigned long *mfn_list, unsigned long nr_mfns) + { + unsigned long flags; + + balloon_lock(flags); + if ( HYPERVISOR_dom_mem_op(MEMOP_decrease_reservation, + mfn_list, nr_mfns, 0) != nr_mfns ) + BUG(); + current_pages -= nr_mfns; /* non-atomic update */ + balloon_unlock(flags); + + schedule_work(&balloon_worker); + } + + EXPORT_SYMBOL(balloon_update_driver_allowance); + EXPORT_SYMBOL(balloon_put_pages); diff --cc linux-2.6.11-xen-sparse/drivers/xen/blkback/vbd.c index 0000000000,b530128366..1aa5acf0c9 mode 000000,100644..100644 --- a/linux-2.6.11-xen-sparse/drivers/xen/blkback/vbd.c +++ b/linux-2.6.11-xen-sparse/drivers/xen/blkback/vbd.c @@@ -1,0 -1,576 +1,577 @@@ + /****************************************************************************** + * blkback/vbd.c + * + * Routines for managing virtual block devices (VBDs). + * + * NOTE: vbd_lock protects updates to the rb_tree against concurrent lookups + * in vbd_translate. All other lookups are implicitly protected because the + * only caller (the control message dispatch routine) serializes the calls. + * + * Copyright (c) 2003-2004, Keir Fraser & Steve Hand + */ + + #include "common.h" + + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + static dev_t vbd_map_devnum(blkif_pdev_t); + #endif + + void vbd_create(blkif_be_vbd_create_t *create) + { + vbd_t *vbd; + rb_node_t **rb_p, *rb_parent = NULL; + blkif_t *blkif; + blkif_vdev_t vdevice = create->vdevice; + + blkif = blkif_find_by_handle(create->domid, create->blkif_handle); + if ( unlikely(blkif == NULL) ) + { + DPRINTK("vbd_create attempted for non-existent blkif (%u,%u)\n", + create->domid, create->blkif_handle); + create->status = BLKIF_BE_STATUS_INTERFACE_NOT_FOUND; + return; + } + + rb_p = &blkif->vbd_rb.rb_node; + while ( *rb_p != NULL ) + { + rb_parent = *rb_p; + vbd = rb_entry(rb_parent, vbd_t, rb); + if ( vdevice < vbd->vdevice ) + { + rb_p = &rb_parent->rb_left; + } + else if ( vdevice > vbd->vdevice ) + { + rb_p = &rb_parent->rb_right; + } + else + { + DPRINTK("vbd_create attempted for already existing vbd\n"); + create->status = BLKIF_BE_STATUS_VBD_EXISTS; + return; + } + } + + if ( unlikely((vbd = kmalloc(sizeof(vbd_t), GFP_KERNEL)) == NULL) ) + { + DPRINTK("vbd_create: out of memory\n"); + create->status = BLKIF_BE_STATUS_OUT_OF_MEMORY; + return; + } + + vbd->vdevice = vdevice; + vbd->readonly = create->readonly; + vbd->type = VDISK_TYPE_DISK | VDISK_FLAG_VIRT; + vbd->extents = NULL; + + spin_lock(&blkif->vbd_lock); + rb_link_node(&vbd->rb, rb_parent, rb_p); + rb_insert_color(&vbd->rb, &blkif->vbd_rb); + spin_unlock(&blkif->vbd_lock); + + DPRINTK("Successful creation of vdev=%04x (dom=%u)\n", + vdevice, create->domid); + create->status = BLKIF_BE_STATUS_OKAY; + } + + + /* Grow a VBD by appending a new extent. Fails if the VBD doesn't exist. */ + void vbd_grow(blkif_be_vbd_grow_t *grow) + { + blkif_t *blkif; + blkif_extent_le_t **px, *x; + vbd_t *vbd = NULL; + rb_node_t *rb; + blkif_vdev_t vdevice = grow->vdevice; + unsigned long sz; + + blkif = blkif_find_by_handle(grow->domid, grow->blkif_handle); + if ( unlikely(blkif == NULL) ) + { + DPRINTK("vbd_grow attempted for non-existent blkif (%u,%u)\n", + grow->domid, grow->blkif_handle); + grow->status = BLKIF_BE_STATUS_INTERFACE_NOT_FOUND; + return; + } + + rb = blkif->vbd_rb.rb_node; + while ( rb != NULL ) + { + vbd = rb_entry(rb, vbd_t, rb); + if ( vdevice < vbd->vdevice ) + rb = rb->rb_left; + else if ( vdevice > vbd->vdevice ) + rb = rb->rb_right; + else + break; + } + + if ( unlikely(vbd == NULL) || unlikely(vbd->vdevice != vdevice) ) + { + DPRINTK("vbd_grow: attempted to append extent to non-existent VBD.\n"); + grow->status = BLKIF_BE_STATUS_VBD_NOT_FOUND; + return; + } + + if ( grow->extent.sector_start > 0 ) + { + DPRINTK("vbd_grow: dev %08x start not zero.\n", grow->extent.device); + grow->status = BLKIF_BE_STATUS_EXTENT_NOT_FOUND; + return; + } + + if ( unlikely((x = kmalloc(sizeof(blkif_extent_le_t), + GFP_KERNEL)) == NULL) ) + { + DPRINTK("vbd_grow: out of memory\n"); + grow->status = BLKIF_BE_STATUS_OUT_OF_MEMORY; + return; + } + - x->extent.device = grow->extent.device; ++ /* Mask to 16-bit for compatibility with old tools */ ++ x->extent.device = grow->extent.device & 0xffff; + x->extent.sector_start = grow->extent.sector_start; + x->extent.sector_length = grow->extent.sector_length; + x->next = (blkif_extent_le_t *)NULL; + + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + x->bdev = open_by_devnum(vbd_map_devnum(x->extent.device), + vbd->readonly ? FMODE_READ : FMODE_WRITE); + if ( IS_ERR(x->bdev) ) + { + DPRINTK("vbd_grow: device %08x doesn't exist.\n", x->extent.device); + grow->status = BLKIF_BE_STATUS_EXTENT_NOT_FOUND; + goto out; + } + /* XXXcl maybe bd_claim? */ + + if ( (x->bdev->bd_disk == NULL) ) + { + DPRINTK("vbd_grow: device %08x doesn't exist.\n", x->extent.device); + grow->status = BLKIF_BE_STATUS_EXTENT_NOT_FOUND; + blkdev_put(x->bdev); + goto out; + } + + /* get size in sectors */ + if ( x->bdev->bd_part ) + sz = x->bdev->bd_part->nr_sects; + else + sz = x->bdev->bd_disk->capacity; + + #else + if( !blk_size[MAJOR(x->extent.device)] ) + { + DPRINTK("vbd_grow: device %08x doesn't exist.\n", x->extent.device); + grow->status = BLKIF_BE_STATUS_EXTENT_NOT_FOUND; + goto out; + } + + /* convert blocks (1KB) to sectors */ + sz = blk_size[MAJOR(x->extent.device)][MINOR(x->extent.device)] * 2; + + if ( sz == 0 ) + { + DPRINTK("vbd_grow: device %08x zero size!\n", x->extent.device); + grow->status = BLKIF_BE_STATUS_EXTENT_NOT_FOUND; + goto out; + } + #endif + + /* + * NB. This test assumes sector_start == 0, which is always the case + * in Xen 1.3. In fact the whole grow/shrink interface could do with + * some simplification. + */ + if ( x->extent.sector_length > sz ) + x->extent.sector_length = sz; + + DPRINTK("vbd_grow: requested_len %llu actual_len %lu\n", + x->extent.sector_length, sz); + + for ( px = &vbd->extents; *px != NULL; px = &(*px)->next ) + continue; + + *px = x; /* ATOMIC: no need for vbd_lock. */ + + DPRINTK("Successful grow of vdev=%04x (dom=%u)\n", + vdevice, grow->domid); + + grow->status = BLKIF_BE_STATUS_OKAY; + return; + + out: + kfree(x); + } + + + void vbd_shrink(blkif_be_vbd_shrink_t *shrink) + { + blkif_t *blkif; + blkif_extent_le_t **px, *x; + vbd_t *vbd = NULL; + rb_node_t *rb; + blkif_vdev_t vdevice = shrink->vdevice; + + blkif = blkif_find_by_handle(shrink->domid, shrink->blkif_handle); + if ( unlikely(blkif == NULL) ) + { + DPRINTK("vbd_shrink attempted for non-existent blkif (%u,%u)\n", + shrink->domid, shrink->blkif_handle); + shrink->status = BLKIF_BE_STATUS_INTERFACE_NOT_FOUND; + return; + } + + rb = blkif->vbd_rb.rb_node; + while ( rb != NULL ) + { + vbd = rb_entry(rb, vbd_t, rb); + if ( vdevice < vbd->vdevice ) + rb = rb->rb_left; + else if ( vdevice > vbd->vdevice ) + rb = rb->rb_right; + else + break; + } + + if ( unlikely(vbd == NULL) || unlikely(vbd->vdevice != vdevice) ) + { + shrink->status = BLKIF_BE_STATUS_VBD_NOT_FOUND; + return; + } + + if ( unlikely(vbd->extents == NULL) ) + { + shrink->status = BLKIF_BE_STATUS_EXTENT_NOT_FOUND; + return; + } + + /* Find the last extent. We now know that there is at least one. */ + for ( px = &vbd->extents; (*px)->next != NULL; px = &(*px)->next ) + continue; + + x = *px; + *px = x->next; /* ATOMIC: no need for vbd_lock. */ + + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + blkdev_put(x->bdev); + #endif + kfree(x); + + shrink->status = BLKIF_BE_STATUS_OKAY; + } + + + void vbd_destroy(blkif_be_vbd_destroy_t *destroy) + { + blkif_t *blkif; + vbd_t *vbd; + rb_node_t *rb; + blkif_extent_le_t *x, *t; + blkif_vdev_t vdevice = destroy->vdevice; + + blkif = blkif_find_by_handle(destroy->domid, destroy->blkif_handle); + if ( unlikely(blkif == NULL) ) + { + DPRINTK("vbd_destroy attempted for non-existent blkif (%u,%u)\n", + destroy->domid, destroy->blkif_handle); + destroy->status = BLKIF_BE_STATUS_INTERFACE_NOT_FOUND; + return; + } + + rb = blkif->vbd_rb.rb_node; + while ( rb != NULL ) + { + vbd = rb_entry(rb, vbd_t, rb); + if ( vdevice < vbd->vdevice ) + rb = rb->rb_left; + else if ( vdevice > vbd->vdevice ) + rb = rb->rb_right; + else + goto found; + } + + destroy->status = BLKIF_BE_STATUS_VBD_NOT_FOUND; + return; + + found: + spin_lock(&blkif->vbd_lock); + rb_erase(rb, &blkif->vbd_rb); + spin_unlock(&blkif->vbd_lock); + + x = vbd->extents; + kfree(vbd); + + while ( x != NULL ) + { + t = x->next; + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + blkdev_put(x->bdev); + #endif + kfree(x); + x = t; + } + } + + + void destroy_all_vbds(blkif_t *blkif) + { + vbd_t *vbd; + rb_node_t *rb; + blkif_extent_le_t *x, *t; + + spin_lock(&blkif->vbd_lock); + + while ( (rb = blkif->vbd_rb.rb_node) != NULL ) + { + vbd = rb_entry(rb, vbd_t, rb); + + rb_erase(rb, &blkif->vbd_rb); + x = vbd->extents; + kfree(vbd); + + while ( x != NULL ) + { + t = x->next; + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + blkdev_put(x->bdev); + #endif + kfree(x); + x = t; + } + } + + spin_unlock(&blkif->vbd_lock); + } + + + static int vbd_probe_single(blkif_t *blkif, vdisk_t *vbd_info, vbd_t *vbd) + { + blkif_extent_le_t *x; + + vbd_info->device = vbd->vdevice; + vbd_info->info = vbd->type; + if ( vbd->readonly ) + vbd_info->info |= VDISK_FLAG_RO; + vbd_info->capacity = 0ULL; + for ( x = vbd->extents; x != NULL; x = x->next ) + vbd_info->capacity += x->extent.sector_length; + + return 0; + } + + + int vbd_probe(blkif_t *blkif, vdisk_t *vbd_info, int max_vbds) + { + int rc = 0, nr_vbds = 0; + rb_node_t *rb; + + spin_lock(&blkif->vbd_lock); + + if ( (rb = blkif->vbd_rb.rb_node) == NULL ) + goto out; + + new_subtree: + /* STEP 1. Find least node (it'll be left-most). */ + while ( rb->rb_left != NULL ) + rb = rb->rb_left; + + for ( ; ; ) + { + /* STEP 2. Dealt with left subtree. Now process current node. */ + if ( (rc = vbd_probe_single(blkif, &vbd_info[nr_vbds], + rb_entry(rb, vbd_t, rb))) != 0 ) + goto out; + if ( ++nr_vbds == max_vbds ) + goto out; + + /* STEP 3. Process right subtree, if any. */ + if ( rb->rb_right != NULL ) + { + rb = rb->rb_right; + goto new_subtree; + } + + /* STEP 4. Done both subtrees. Head back through ancesstors. */ + for ( ; ; ) + { + /* We're done when we get back to the root node. */ + if ( rb->rb_parent == NULL ) + goto out; + /* If we are left of parent, then parent is next to process. */ + if ( rb->rb_parent->rb_left == rb ) + break; + /* If we are right of parent, then we climb to grandparent. */ + rb = rb->rb_parent; + } + + rb = rb->rb_parent; + } + + out: + spin_unlock(&blkif->vbd_lock); + return (rc == 0) ? nr_vbds : rc; + } + + + int vbd_translate(phys_seg_t *pseg, blkif_t *blkif, int operation) + { + blkif_extent_le_t *x; + vbd_t *vbd; + rb_node_t *rb; + blkif_sector_t sec_off; + unsigned long nr_secs; + + /* Take the vbd_lock because another thread could be updating the tree. */ + spin_lock(&blkif->vbd_lock); + + rb = blkif->vbd_rb.rb_node; + while ( rb != NULL ) + { + vbd = rb_entry(rb, vbd_t, rb); + if ( pseg->dev < vbd->vdevice ) + rb = rb->rb_left; + else if ( pseg->dev > vbd->vdevice ) + rb = rb->rb_right; + else + goto found; + } + + DPRINTK("vbd_translate; domain %u attempted to access " + "non-existent VBD.\n", blkif->domid); + + spin_unlock(&blkif->vbd_lock); + return -ENODEV; + + found: + + if ( (operation == WRITE) && vbd->readonly ) + { + spin_unlock(&blkif->vbd_lock); + return -EACCES; + } + + /* + * Now iterate through the list of blkif_extents, working out which should + * be used to perform the translation. + */ + sec_off = pseg->sector_number; + nr_secs = pseg->nr_sects; + for ( x = vbd->extents; x != NULL; x = x->next ) + { + if ( sec_off < x->extent.sector_length ) + { + pseg->dev = x->extent.device; + pseg->bdev = x->bdev; + pseg->sector_number = x->extent.sector_start + sec_off; + if ( unlikely((sec_off + nr_secs) > x->extent.sector_length) ) + goto overrun; + spin_unlock(&blkif->vbd_lock); + return 1; + } + sec_off -= x->extent.sector_length; + } + + DPRINTK("vbd_translate: end of vbd.\n"); + spin_unlock(&blkif->vbd_lock); + return -EACCES; + + /* + * Here we deal with overrun onto the following extent. We don't deal with + * overrun of more than one boundary since each request is restricted to + * 2^9 512-byte sectors, so it should be trivial for control software to + * ensure that extents are large enough to prevent excessive overrun. + */ + overrun: + + /* Adjust length of first chunk to run to end of first extent. */ + pseg[0].nr_sects = x->extent.sector_length - sec_off; + + /* Set second chunk buffer and length to start where first chunk ended. */ + pseg[1].buffer = pseg[0].buffer + (pseg[0].nr_sects << 9); + pseg[1].nr_sects = nr_secs - pseg[0].nr_sects; + + /* Now move to the next extent. Check it exists and is long enough! */ + if ( unlikely((x = x->next) == NULL) || + unlikely(x->extent.sector_length < pseg[1].nr_sects) ) + { + DPRINTK("vbd_translate: multiple overruns or end of vbd.\n"); + spin_unlock(&blkif->vbd_lock); + return -EACCES; + } + + /* Store the real device and start sector for the second chunk. */ + pseg[1].dev = x->extent.device; + pseg[1].bdev = x->bdev; + pseg[1].sector_number = x->extent.sector_start; + + spin_unlock(&blkif->vbd_lock); + return 2; + } + + + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + + #define MAJOR_XEN(dev) ((dev)>>8) + #define MINOR_XEN(dev) ((dev) & 0xff) + + #ifndef FANCY_REMAPPING + static dev_t vbd_map_devnum(blkif_pdev_t cookie) + { + int major = MAJOR_XEN(cookie); + int minor = MINOR_XEN(cookie); + + return MKDEV(major, minor); + } + #else + #define XEN_IDE0_MAJOR IDE0_MAJOR + #define XEN_IDE1_MAJOR IDE1_MAJOR + #define XEN_IDE2_MAJOR IDE2_MAJOR + #define XEN_IDE3_MAJOR IDE3_MAJOR + #define XEN_IDE4_MAJOR IDE4_MAJOR + #define XEN_IDE5_MAJOR IDE5_MAJOR + #define XEN_IDE6_MAJOR IDE6_MAJOR + #define XEN_IDE7_MAJOR IDE7_MAJOR + #define XEN_IDE8_MAJOR IDE8_MAJOR + #define XEN_IDE9_MAJOR IDE9_MAJOR + #define XEN_SCSI_DISK0_MAJOR SCSI_DISK0_MAJOR + #define XEN_SCSI_DISK1_MAJOR SCSI_DISK1_MAJOR + #define XEN_SCSI_DISK2_MAJOR SCSI_DISK2_MAJOR + #define XEN_SCSI_DISK3_MAJOR SCSI_DISK3_MAJOR + #define XEN_SCSI_DISK4_MAJOR SCSI_DISK4_MAJOR + #define XEN_SCSI_DISK5_MAJOR SCSI_DISK5_MAJOR + #define XEN_SCSI_DISK6_MAJOR SCSI_DISK6_MAJOR + #define XEN_SCSI_DISK7_MAJOR SCSI_DISK7_MAJOR + #define XEN_SCSI_CDROM_MAJOR SCSI_CDROM_MAJOR + + static dev_t vbd_map_devnum(blkif_pdev_t cookie) + { + int new_major; + int major = MAJOR_XEN(cookie); + int minor = MINOR_XEN(cookie); + + switch (major) { + case XEN_IDE0_MAJOR: new_major = IDE0_MAJOR; break; + case XEN_IDE1_MAJOR: new_major = IDE1_MAJOR; break; + case XEN_IDE2_MAJOR: new_major = IDE2_MAJOR; break; + case XEN_IDE3_MAJOR: new_major = IDE3_MAJOR; break; + case XEN_IDE4_MAJOR: new_major = IDE4_MAJOR; break; + case XEN_IDE5_MAJOR: new_major = IDE5_MAJOR; break; + case XEN_IDE6_MAJOR: new_major = IDE6_MAJOR; break; + case XEN_IDE7_MAJOR: new_major = IDE7_MAJOR; break; + case XEN_IDE8_MAJOR: new_major = IDE8_MAJOR; break; + case XEN_IDE9_MAJOR: new_major = IDE9_MAJOR; break; + case XEN_SCSI_DISK0_MAJOR: new_major = SCSI_DISK0_MAJOR; break; + case XEN_SCSI_DISK1_MAJOR ... XEN_SCSI_DISK7_MAJOR: + new_major = SCSI_DISK1_MAJOR + major - XEN_SCSI_DISK1_MAJOR; + break; + case XEN_SCSI_CDROM_MAJOR: new_major = SCSI_CDROM_MAJOR; break; + default: new_major = 0; break; + } + + return MKDEV(new_major, minor); + } + #endif + + #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION_CODE(2,6,0) */ diff --cc linux-2.6.11-xen-sparse/drivers/xen/console/console.c index 0000000000,b9c09c3d73..f1fe3c517f mode 000000,100644..100644 --- a/linux-2.6.11-xen-sparse/drivers/xen/console/console.c +++ b/linux-2.6.11-xen-sparse/drivers/xen/console/console.c @@@ -1,0 -1,772 +1,768 @@@ + /****************************************************************************** + * console.c + * + * Virtual console driver. + * + * Copyright (c) 2002-2004, K A Fraser. + * + * This file may be distributed separately from the Linux kernel, or + * incorporated into other software packages, subject to the following license: + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this source file (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + + /* + * Modes: + * 'xencons=off' [XC_OFF]: Console is disabled. + * 'xencons=tty' [XC_TTY]: Console attached to '/dev/tty[0-9]+'. + * 'xencons=ttyS' [XC_SERIAL]: Console attached to '/dev/ttyS[0-9]+'. + * [XC_DEFAULT]: DOM0 -> XC_SERIAL ; all others -> XC_TTY. + * + * NB. In mode XC_TTY, we create dummy consoles for tty2-63. This suppresses + * warnings from standard distro startup scripts. + */ + static enum { XC_OFF, XC_DEFAULT, XC_TTY, XC_SERIAL } xc_mode = XC_DEFAULT; + + static int __init xencons_setup(char *str) + { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - if (str[0] == '=') - str++; -#endif + if ( !strcmp(str, "tty") ) + xc_mode = XC_TTY; + else if ( !strcmp(str, "ttyS") ) + xc_mode = XC_SERIAL; + else if ( !strcmp(str, "off") ) + xc_mode = XC_OFF; + return 1; + } -__setup("xencons", xencons_setup); ++__setup("xencons=", xencons_setup); + + /* The kernel and user-land drivers share a common transmit buffer. */ + #define WBUF_SIZE 4096 + #define WBUF_MASK(_i) ((_i)&(WBUF_SIZE-1)) + static char wbuf[WBUF_SIZE]; + static unsigned int wc, wp; /* write_cons, write_prod */ + + /* This lock protects accesses to the common transmit buffer. */ + static spinlock_t xencons_lock = SPIN_LOCK_UNLOCKED; + + /* Common transmit-kick routine. */ + static void __xencons_tx_flush(void); + + /* This task is used to defer sending console data until there is space. */ + static void xencons_tx_flush_task_routine(void *data); + + static DECLARE_TQUEUE(xencons_tx_flush_task, + xencons_tx_flush_task_routine, + NULL); + + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + static struct tty_driver *xencons_driver; + #else + static struct tty_driver xencons_driver; + #endif + + + /******************** Kernel console driver ********************************/ + + static void kcons_write( + struct console *c, const char *s, unsigned int count) + { + int i; + unsigned long flags; + + spin_lock_irqsave(&xencons_lock, flags); + + for ( i = 0; i < count; i++ ) + { + if ( (wp - wc) >= (WBUF_SIZE - 1) ) + break; + if ( (wbuf[WBUF_MASK(wp++)] = s[i]) == '\n' ) + wbuf[WBUF_MASK(wp++)] = '\r'; + } + + __xencons_tx_flush(); + + spin_unlock_irqrestore(&xencons_lock, flags); + } + + static void kcons_write_dom0( + struct console *c, const char *s, unsigned int count) + { + int rc; + + while ( count > 0 ) + { + if ( (rc = HYPERVISOR_console_io(CONSOLEIO_write, + count, (char *)s)) > 0 ) + { + count -= rc; + s += rc; + } + else + break; + } + } + + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + static struct tty_driver *kcons_device(struct console *c, int *index) + { + *index = c->index; + return xencons_driver; + } + #else + static kdev_t kcons_device(struct console *c) + { + return MKDEV(TTY_MAJOR, (xc_mode == XC_SERIAL) ? 64 : 1); + } + #endif + + static struct console kcons_info = { + device: kcons_device, + flags: CON_PRINTBUFFER, + index: -1 + }; + + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + #define __RETCODE 0 + static int __init xen_console_init(void) + #else + #define __RETCODE + void xen_console_init(void) + #endif + { + if ( xen_start_info.flags & SIF_INITDOMAIN ) + { + if ( xc_mode == XC_DEFAULT ) + xc_mode = XC_SERIAL; + kcons_info.write = kcons_write_dom0; + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + if ( xc_mode == XC_SERIAL ) + kcons_info.flags |= CON_ENABLED; + #endif + } + else + { + if ( xc_mode == XC_DEFAULT ) + xc_mode = XC_TTY; + kcons_info.write = kcons_write; + } + + if ( xc_mode == XC_OFF ) + return __RETCODE; + + if ( xc_mode == XC_SERIAL ) + strcpy(kcons_info.name, "ttyS"); + else + strcpy(kcons_info.name, "tty"); + + register_console(&kcons_info); + return __RETCODE; + } + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + console_initcall(xen_console_init); + #endif + + /*** Useful function for console debugging -- goes straight to Xen. ***/ + asmlinkage int xprintk(const char *fmt, ...) + { + va_list args; + int printk_len; + static char printk_buf[1024]; + + /* Emit the output into the temporary buffer */ + va_start(args, fmt); + printk_len = vsnprintf(printk_buf, sizeof(printk_buf), fmt, args); + va_end(args); + + /* Send the processed output directly to Xen. */ + kcons_write_dom0(NULL, printk_buf, printk_len); + + return 0; + } + + /*** Forcibly flush console data before dying. ***/ + void xencons_force_flush(void) + { + ctrl_msg_t msg; + int sz; + + /* Emergency console is synchronous, so there's nothing to flush. */ + if ( xen_start_info.flags & SIF_INITDOMAIN ) + return; + + /* + * We use dangerous control-interface functions that require a quiescent + * system and no interrupts. Try to ensure this with a global cli(). + */ + cli(); + + /* Spin until console data is flushed through to the domain controller. */ + while ( (wc != wp) && !ctrl_if_transmitter_empty() ) + { + /* Interrupts are disabled -- we must manually reap responses. */ + ctrl_if_discard_responses(); + + if ( (sz = wp - wc) == 0 ) + continue; + if ( sz > sizeof(msg.msg) ) + sz = sizeof(msg.msg); + if ( sz > (WBUF_SIZE - WBUF_MASK(wc)) ) + sz = WBUF_SIZE - WBUF_MASK(wc); + + msg.type = CMSG_CONSOLE; + msg.subtype = CMSG_CONSOLE_DATA; + msg.length = sz; + memcpy(msg.msg, &wbuf[WBUF_MASK(wc)], sz); + + if ( ctrl_if_send_message_noblock(&msg, NULL, 0) == 0 ) + wc += sz; + } + } + + + /******************** User-space console driver (/dev/console) ************/ + + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + #define DRV(_d) (_d) + #define TTY_INDEX(_tty) ((_tty)->index) + #else + static int xencons_refcount; + static struct tty_struct *xencons_table[MAX_NR_CONSOLES]; + #define DRV(_d) (&(_d)) + #define TTY_INDEX(_tty) (MINOR((_tty)->device) - xencons_driver.minor_start) + #endif + + static struct termios *xencons_termios[MAX_NR_CONSOLES]; + static struct termios *xencons_termios_locked[MAX_NR_CONSOLES]; + static struct tty_struct *xencons_tty; + static int xencons_priv_irq; + static char x_char; + + /* Non-privileged receive callback. */ + static void xencons_rx(ctrl_msg_t *msg, unsigned long id) + { + int i; + unsigned long flags; + + spin_lock_irqsave(&xencons_lock, flags); + if ( xencons_tty != NULL ) + { + for ( i = 0; i < msg->length; i++ ) + tty_insert_flip_char(xencons_tty, msg->msg[i], 0); + tty_flip_buffer_push(xencons_tty); + } + spin_unlock_irqrestore(&xencons_lock, flags); + + msg->length = 0; + ctrl_if_send_response(msg); + } + + /* Privileged and non-privileged transmit worker. */ + static void __xencons_tx_flush(void) + { + int sz, work_done = 0; + ctrl_msg_t msg; + + if ( xen_start_info.flags & SIF_INITDOMAIN ) + { + if ( x_char ) + { + kcons_write_dom0(NULL, &x_char, 1); + x_char = 0; + work_done = 1; + } + + while ( wc != wp ) + { + sz = wp - wc; + if ( sz > (WBUF_SIZE - WBUF_MASK(wc)) ) + sz = WBUF_SIZE - WBUF_MASK(wc); + kcons_write_dom0(NULL, &wbuf[WBUF_MASK(wc)], sz); + wc += sz; + work_done = 1; + } + } + else + { + while ( x_char ) + { + msg.type = CMSG_CONSOLE; + msg.subtype = CMSG_CONSOLE_DATA; + msg.length = 1; + msg.msg[0] = x_char; + + if ( ctrl_if_send_message_noblock(&msg, NULL, 0) == 0 ) + x_char = 0; + else if ( ctrl_if_enqueue_space_callback(&xencons_tx_flush_task) ) + break; + + work_done = 1; + } + + while ( wc != wp ) + { + sz = wp - wc; + if ( sz > sizeof(msg.msg) ) + sz = sizeof(msg.msg); + if ( sz > (WBUF_SIZE - WBUF_MASK(wc)) ) + sz = WBUF_SIZE - WBUF_MASK(wc); + + msg.type = CMSG_CONSOLE; + msg.subtype = CMSG_CONSOLE_DATA; + msg.length = sz; + memcpy(msg.msg, &wbuf[WBUF_MASK(wc)], sz); + + if ( ctrl_if_send_message_noblock(&msg, NULL, 0) == 0 ) + wc += sz; + else if ( ctrl_if_enqueue_space_callback(&xencons_tx_flush_task) ) + break; + + work_done = 1; + } + } + + if ( work_done && (xencons_tty != NULL) ) + { + wake_up_interruptible(&xencons_tty->write_wait); + if ( (xencons_tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && + (xencons_tty->ldisc.write_wakeup != NULL) ) + (xencons_tty->ldisc.write_wakeup)(xencons_tty); + } + } + + /* Non-privileged transmit kicker. */ + static void xencons_tx_flush_task_routine(void *data) + { + unsigned long flags; + spin_lock_irqsave(&xencons_lock, flags); + __xencons_tx_flush(); + spin_unlock_irqrestore(&xencons_lock, flags); + } + + /* Privileged receive callback and transmit kicker. */ + static irqreturn_t xencons_priv_interrupt(int irq, void *dev_id, + struct pt_regs *regs) + { + static char rbuf[16]; + int i, l; + unsigned long flags; + + spin_lock_irqsave(&xencons_lock, flags); + + if ( xencons_tty != NULL ) + { + /* Receive work. */ + while ( (l = HYPERVISOR_console_io(CONSOLEIO_read, 16, rbuf)) > 0 ) + for ( i = 0; i < l; i++ ) + tty_insert_flip_char(xencons_tty, rbuf[i], 0); + if ( xencons_tty->flip.count != 0 ) + tty_flip_buffer_push(xencons_tty); + } + + /* Transmit work. */ + __xencons_tx_flush(); + + spin_unlock_irqrestore(&xencons_lock, flags); + + return IRQ_HANDLED; + } + + static int xencons_write_room(struct tty_struct *tty) + { + return WBUF_SIZE - (wp - wc); + } + + static int xencons_chars_in_buffer(struct tty_struct *tty) + { + return wp - wc; + } + + static void xencons_send_xchar(struct tty_struct *tty, char ch) + { + unsigned long flags; + + if ( TTY_INDEX(tty) != 0 ) + return; + + spin_lock_irqsave(&xencons_lock, flags); + x_char = ch; + __xencons_tx_flush(); + spin_unlock_irqrestore(&xencons_lock, flags); + } + + static void xencons_throttle(struct tty_struct *tty) + { + if ( TTY_INDEX(tty) != 0 ) + return; + + if ( I_IXOFF(tty) ) + xencons_send_xchar(tty, STOP_CHAR(tty)); + } + + static void xencons_unthrottle(struct tty_struct *tty) + { + if ( TTY_INDEX(tty) != 0 ) + return; + + if ( I_IXOFF(tty) ) + { + if ( x_char != 0 ) + x_char = 0; + else + xencons_send_xchar(tty, START_CHAR(tty)); + } + } + + static void xencons_flush_buffer(struct tty_struct *tty) + { + unsigned long flags; + + if ( TTY_INDEX(tty) != 0 ) + return; + + spin_lock_irqsave(&xencons_lock, flags); + wc = wp = 0; + spin_unlock_irqrestore(&xencons_lock, flags); + } + + static inline int __xencons_put_char(int ch) + { + char _ch = (char)ch; + if ( (wp - wc) == WBUF_SIZE ) + return 0; + wbuf[WBUF_MASK(wp++)] = _ch; + return 1; + } + + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + static int xencons_write(struct tty_struct *tty, const unsigned char *buf, + int count) + { + int i; + unsigned long flags; + + if ( TTY_INDEX(tty) != 0 ) + return count; + + spin_lock_irqsave(&xencons_lock, flags); + + for ( i = 0; i < count; i++ ) + if ( !__xencons_put_char(buf[i]) ) + break; + + if ( i != 0 ) + __xencons_tx_flush(); + + spin_unlock_irqrestore(&xencons_lock, flags); + + return i; + } + #else + static int xencons_write(struct tty_struct *tty, int from_user, + const u_char *buf, int count) + { + int i; + unsigned long flags; + + if ( from_user && verify_area(VERIFY_READ, buf, count) ) + return -EINVAL; + + if ( TTY_INDEX(tty) != 0 ) + return count; + + spin_lock_irqsave(&xencons_lock, flags); + + for ( i = 0; i < count; i++ ) + { + char ch; + if ( from_user ) + __get_user(ch, buf + i); + else + ch = buf[i]; + if ( !__xencons_put_char(ch) ) + break; + } + + if ( i != 0 ) + __xencons_tx_flush(); + + spin_unlock_irqrestore(&xencons_lock, flags); + + return i; + } + #endif + + static void xencons_put_char(struct tty_struct *tty, u_char ch) + { + unsigned long flags; + + if ( TTY_INDEX(tty) != 0 ) + return; + + spin_lock_irqsave(&xencons_lock, flags); + (void)__xencons_put_char(ch); + spin_unlock_irqrestore(&xencons_lock, flags); + } + + static void xencons_flush_chars(struct tty_struct *tty) + { + unsigned long flags; + + if ( TTY_INDEX(tty) != 0 ) + return; + + spin_lock_irqsave(&xencons_lock, flags); + __xencons_tx_flush(); + spin_unlock_irqrestore(&xencons_lock, flags); + } + + static void xencons_wait_until_sent(struct tty_struct *tty, int timeout) + { + unsigned long orig_jiffies = jiffies; + + if ( TTY_INDEX(tty) != 0 ) + return; + + while ( DRV(tty->driver)->chars_in_buffer(tty) ) + { + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(1); + if ( signal_pending(current) ) + break; + if ( (timeout != 0) && time_after(jiffies, orig_jiffies + timeout) ) + break; + } + + set_current_state(TASK_RUNNING); + } + + static int xencons_open(struct tty_struct *tty, struct file *filp) + { + unsigned long flags; + + if ( TTY_INDEX(tty) != 0 ) + return 0; + + spin_lock_irqsave(&xencons_lock, flags); + tty->driver_data = NULL; + if ( xencons_tty == NULL ) + xencons_tty = tty; + __xencons_tx_flush(); + spin_unlock_irqrestore(&xencons_lock, flags); + + return 0; + } + + static void xencons_close(struct tty_struct *tty, struct file *filp) + { + unsigned long flags; + + if ( TTY_INDEX(tty) != 0 ) + return; + + if ( tty->count == 1 ) + { + tty->closing = 1; + tty_wait_until_sent(tty, 0); + if ( DRV(tty->driver)->flush_buffer != NULL ) + DRV(tty->driver)->flush_buffer(tty); + if ( tty->ldisc.flush_buffer != NULL ) + tty->ldisc.flush_buffer(tty); + tty->closing = 0; + spin_lock_irqsave(&xencons_lock, flags); + xencons_tty = NULL; + spin_unlock_irqrestore(&xencons_lock, flags); + } + } + + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + static struct tty_operations xencons_ops = { + .open = xencons_open, + .close = xencons_close, + .write = xencons_write, + .write_room = xencons_write_room, + .put_char = xencons_put_char, + .flush_chars = xencons_flush_chars, + .chars_in_buffer = xencons_chars_in_buffer, + .send_xchar = xencons_send_xchar, + .flush_buffer = xencons_flush_buffer, + .throttle = xencons_throttle, + .unthrottle = xencons_unthrottle, + .wait_until_sent = xencons_wait_until_sent, + }; + + #ifdef CONFIG_XEN_PRIVILEGED_GUEST + static const char *xennullcon_startup(void) + { + return NULL; + } + + static int xennullcon_dummy(void) + { + return 0; + } + + #define DUMMY (void *)xennullcon_dummy + + /* + * The console `switch' structure for the dummy console + * + * Most of the operations are dummies. + */ + + const struct consw xennull_con = { + .owner = THIS_MODULE, + .con_startup = xennullcon_startup, + .con_init = DUMMY, + .con_deinit = DUMMY, + .con_clear = DUMMY, + .con_putc = DUMMY, + .con_putcs = DUMMY, + .con_cursor = DUMMY, + .con_scroll = DUMMY, + .con_bmove = DUMMY, + .con_switch = DUMMY, + .con_blank = DUMMY, + .con_font_set = DUMMY, + .con_font_get = DUMMY, + .con_font_default = DUMMY, + .con_font_copy = DUMMY, + .con_set_palette = DUMMY, + .con_scrolldelta = DUMMY, + }; + #endif + #endif + + static int __init xencons_init(void) + { + int rc; + + if ( xc_mode == XC_OFF ) + return 0; + + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + xencons_driver = alloc_tty_driver((xc_mode == XC_SERIAL) ? + 1 : MAX_NR_CONSOLES); + if ( xencons_driver == NULL ) + return -ENOMEM; + #else + memset(&xencons_driver, 0, sizeof(struct tty_driver)); + xencons_driver.magic = TTY_DRIVER_MAGIC; + xencons_driver.refcount = &xencons_refcount; + xencons_driver.table = xencons_table; + xencons_driver.num = (xc_mode == XC_SERIAL) ? 1 : MAX_NR_CONSOLES; + #endif + + DRV(xencons_driver)->major = TTY_MAJOR; + DRV(xencons_driver)->type = TTY_DRIVER_TYPE_SERIAL; + DRV(xencons_driver)->subtype = SERIAL_TYPE_NORMAL; + DRV(xencons_driver)->init_termios = tty_std_termios; + DRV(xencons_driver)->flags = + TTY_DRIVER_REAL_RAW | TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_NO_DEVFS; + DRV(xencons_driver)->termios = xencons_termios; + DRV(xencons_driver)->termios_locked = xencons_termios_locked; + + if ( xc_mode == XC_SERIAL ) + { + DRV(xencons_driver)->name = "ttyS"; + DRV(xencons_driver)->minor_start = 64; + DRV(xencons_driver)->name_base = 0; + } + else + { + DRV(xencons_driver)->name = "tty"; + DRV(xencons_driver)->minor_start = 1; + DRV(xencons_driver)->name_base = 1; + } + + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + tty_set_operations(xencons_driver, &xencons_ops); + #else + xencons_driver.open = xencons_open; + xencons_driver.close = xencons_close; + xencons_driver.write = xencons_write; + xencons_driver.write_room = xencons_write_room; + xencons_driver.put_char = xencons_put_char; + xencons_driver.flush_chars = xencons_flush_chars; + xencons_driver.chars_in_buffer = xencons_chars_in_buffer; + xencons_driver.send_xchar = xencons_send_xchar; + xencons_driver.flush_buffer = xencons_flush_buffer; + xencons_driver.throttle = xencons_throttle; + xencons_driver.unthrottle = xencons_unthrottle; + xencons_driver.wait_until_sent = xencons_wait_until_sent; + #endif + + if ( (rc = tty_register_driver(DRV(xencons_driver))) != 0 ) + { + printk("WARNING: Failed to register Xen virtual " + "console driver as '%s%d'\n", + DRV(xencons_driver)->name, DRV(xencons_driver)->name_base); + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + put_tty_driver(xencons_driver); + xencons_driver = NULL; + #endif + return rc; + } + + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + tty_register_device(xencons_driver, 0, NULL); + #endif + + if ( xen_start_info.flags & SIF_INITDOMAIN ) + { + xencons_priv_irq = bind_virq_to_irq(VIRQ_CONSOLE); + (void)request_irq(xencons_priv_irq, + xencons_priv_interrupt, 0, "console", NULL); + } + else + { + (void)ctrl_if_register_receiver(CMSG_CONSOLE, xencons_rx, 0); + } + + printk("Xen virtual console successfully installed as %s\n", + DRV(xencons_driver)->name); + + return 0; + } + + module_init(xencons_init);